#ifndef QQuickROChannel_H
#define QQuickROChannel_H

#include <QObject>
#include <QHostAddress>
#include <QVariant>
#include <QDateTime>
#include <QTimer>


class QQuickROChannel;

class QTcpSocket;
class QUdpSocket;
class QTcpServer;



class QQuickROChannelServer:public QObject
{
    Q_OBJECT
public:
    QQuickROChannelServer(QObject* parent = nullptr);

public:
    bool listen(QHostAddress address,int port);

    QList<QQuickROChannel *> channels() const;
signals:
    void newConnection(QQuickROChannel* con);
private:
    void onNewTcpConnection(QTcpSocket* socket);
    int allocConId();
private:
    QMap<int,QQuickROChannel*> m_channels;
    QMap<int,QQuickROChannel*> m_tempChannels;
    QTcpServer *m_tcpServer;
    QUdpSocket* m_udpServer;
    int maxConId = 0;
    friend class QQuickROChannel;
};

class QQuickROChannel:public QObject
{
    Q_OBJECT

private:
    struct SenderInfo
    {
        enum Type
        {
            Tcp,
            Udp
        };

        Type type;

        QHostAddress udpaddress;
        int udpport = 0;

    };

public:



    enum State
    {
        Default,
        ConnectingToHost,
        ConnectingToClient,
        Ready,
        Disconnected
    };
    Q_ENUM(State)

    enum MessagePolicy//报文信息的发送类型
    {
        Safe,//更安全的发送消息，确保消息一定到达。底层使用tcp
        Quick//更快速的发送消息，消息不一定有序和可达。底层使用udp
    };
    Q_ENUM(MessagePolicy)

    Q_PROPERTY(State state READ state WRITE setState NOTIFY stateChanged)
public:
    QQuickROChannel(QObject* parent = nullptr);
    ~QQuickROChannel();

    void connectTo(QHostAddress address,int port);

    void disconnect();//与服务器（客户端）断开连接

    void write(QString topic,QVariant value,MessagePolicy = Safe);

    State state();

    int id();//链接id
signals:
    void newMessage(QString topic,QVariant value);
    void stateChanged();
private:
    void setState(State state);
    void connectToClient(QQuickROChannelServer* server,QTcpSocket* socket,int conId);
    void onMessage(QString topic,QVariant value,const SenderInfo& sender);
    void onTcpReadyRead();
    void onTcpDisconnected();
    void onUdpReadyRead();
    QVariant getChannelInfo();
private:
    struct ServerData;
    struct ClientData;
    ServerData *m_sData = nullptr;
    ClientData * m_cData = nullptr;
    QTcpSocket* m_tcpSocket = nullptr;
    QHostAddress m_peerUdpAddress;
    int m_peerUdpPort = 0;
    State m_state = Default;
    int conId = 0;

    friend class QQuickROChannelServer;
};


#endif
